#ifndef ANIMAL_PLUS_H_
#define ANIMAL_PLUS_H_

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

//  前向声明
struct Animal;

//  虚函数表(相当于C++的vtable)
typedef struct AnimalVTable{
    void (*Speak)(struct Animal* self);
    void (*Dothing)(struct Animal* self);
    void (*Destroy)(struct Animal* self);
} AnimalVTable;

//  基类 Animal(相当于父类)
typedef struct Animal{
    char* name;
    //  指向虚函数表
    const AnimalVTable* vtbl;
} Animal;

//  构造函数声明
Animal* Animal_Create(const char* name);
void Animal_Speak(Animal* self);
void Animal_Dothing(Animal* self);
void Animal_Destroy(Animal* self);

//  我们可以让Animal成为 “抽象类”，不直接使用
static void Animal_Speak_Default(Animal* self){
    printf("Animal %s makes a sound.\n", self->name);
}

static void Animal_Dothing_Default(Animal* self){
    printf("Animal %s does something.\n", self->name);
}

static void Animal_Destroy_Base(Animal* self){
    free(self->name);
    free(self);
}

//  虚函数表（默认行为，也可以设为NULL表示纯虚）
static const AnimalVTable Animal_VTable = {
    Animal_Speak_Default,
    Animal_Dothing_Default,
    Animal_Destroy_Base
};


Animal* Animal_Create(const char* name){
    Animal* self = (Animal*)malloc(sizeof(Animal));
    if(!self)
        return NULL;

    self->name = strdup(name);
    if(!self->name){
        free(self);
        return NULL;
    }

    self->vtbl = &Animal_VTable;
    return self;
}

//  封装接口
void Animal_Speak(Animal* self){
    self->vtbl->Speak(self);
}

void Animal_Dothing(Animal* self){
    self->vtbl->Dothing(self);
}

void Animal_Destroy(Animal* self){
    self->vtbl->Destroy(self);
}


//  定义子类

typedef struct Dog{
    Animal base;
} Dog;

Dog* Dog_Create(const char* name);

static void Dog_Speak(Dog* self){
    printf("%s says: 汪汪汪\n", self->base.name);
}

static void Dog_Dothing(Dog* self){
    printf("%s is seeing the door.\n", self->base.name);
}

static void Dog_Destroy(Dog* self){
    free(self->base.name);
    free(self);
}


static const AnimalVTable Dog_VTable = {
    //  强转为基类函数指针
    (void(*)(Animal*))Dog_Speak,
    (void(*)(Animal*))Dog_Dothing,
    (void(*)(Animal*))Dog_Destroy
};

Dog* Dog_Create(const char * name){
    Dog* self = (Dog*)malloc(sizeof(Dog));
    if(!self)
        return NULL;
    self->base.name = strdup(name);
    if(!self->base.name){
        free(self);
        return NULL;
    }

    self->base.vtbl = &Dog_VTable;
    return self;
}

typedef struct Cat{
    Animal base;
} Cat;

Cat* Cat_Create(const char* name);


static void Cat_Speak(Cat* self){
    printf("%s says: 喵喵喵!\n", self->base.name);
}

static void Cat_Dothing(Cat* self){
    printf("%s is catching mice.\n", self->base.name);
}

static void Cat_Destroy(Cat* self){
    free(self->base.name);
    free(self);
}

static const AnimalVTable Cat_VTable = {
    (void(*)(Animal*))Cat_Speak,
    (void(*)(Animal*))Cat_Dothing,
    (void(*)(Animal*))Cat_Destroy
};

Cat* Cat_Create(const char* name){
    Cat* self = (Cat*)malloc(sizeof(Cat));
    if(!self)
        return NULL;
    self->base.name = strdup(name);
    if(!self->base.name){
        free(self);
        return NULL;
    }

    self->base.vtbl = &Cat_VTable;
    return self;
}


#endif

int main(){
    Animal* animals[2];

    animals[0] = (Animal*)Dog_Create("Tom");
    animals[1] = (Animal*)Cat_Create("Aim");

    for(int i = 0; i < 2; i++){
        Animal_Speak(animals[i]);
        Animal_Dothing(animals[i]);
    }

    return 0;
}